package cn.virens.common.boot.provider.apijson;

import apijson.orm.AbstractParser;
import apijson.orm.SQLConfig;
import cn.virens.common.boot.provider.apijson.autoconfig.ApijsonProperties;
import cn.virens.common.util.exception.APIException;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

import javax.sql.DataSource;

public class APIJSONParser extends AbstractParser<String, JSONObject, JSONArray> {
    private final VirValue<APIJSONParserFunction> fparser = new VirValue<>();
    private final VirValue<APIJSONSQLExecutor> executor = new VirValue<>();
    private final VirValue<APIJSONSQLConfig> config = new VirValue<>();
    private final VirValue<APIJSONVerifier> verifier = new VirValue<>();

    protected final ApijsonProperties props;
    protected final DataSource dataSource;

    public APIJSONParser(DataSource dataSource, ApijsonProperties props) {
        this.setNeedVerifyContent(props.getNeedVerifyContent());
        this.setNeedVerifyLogin(props.getNeedVerifyLogin());
        this.setNeedVerifyRole(props.getNeedVerifyRole());
        this.setMethod(props.getMethod());

        this.dataSource = dataSource;
        this.props = props;
    }

    @Override
    public APIJSONParserFunction createFunctionParser() throws APIException {
        return fparser.get(() -> new APIJSONParserFunction(this));
    }

    @Override
    public APIJSONSQLExecutor createSQLExecutor() throws APIException {
        return executor.get(() -> new APIJSONSQLExecutor(this));
    }

    @Override
    public APIJSONSQLConfig createSQLConfig() throws APIException {
        return config.get(() -> new APIJSONSQLConfig(this));
    }

    @Override
    public APIJSONVerifier createVerifier() throws APIException {
        return verifier.get(() -> new APIJSONVerifier(this));
    }

    @Override
    public APIJSONParser createParser() throws APIException {
        return new APIJSONParser(dataSource, props);
    }

    @Override
    public Object onFunctionParse(String key, String function, String parentPath, String currentName, JSONObject currentObject, boolean containRaw) throws Exception {
        APIJSONParserFunction apijsonParserFunction = createFunctionParser();

        apijsonParserFunction.setCurrentObject(currentObject);
        apijsonParserFunction.setCurrentName(currentName);
        apijsonParserFunction.setParentPath(parentPath);
        apijsonParserFunction.setKey(key);

        return apijsonParserFunction.invoke(function, currentObject, containRaw);
    }

    @Override
    public APIJSONParserObject createObjectParser(JSONObject request, String parentPath, SQLConfig<String, JSONObject, JSONArray> arrayConfig, boolean isSubquery, boolean isTable, boolean isArrayMainTable) throws Exception {
        return new APIJSONParserObject(this, request, parentPath, arrayConfig, isSubquery, isTable, isArrayMainTable);
    }
}
